/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package AccesoDatos.Persistencia.Manager;

import AccesoDatos.Persistencia.Entidad.EAsignado;
import AccesoDatos.Persistencia.Entidad.EDescribir;
import AccesoDatos.Persistencia.Entidad.EEscrito;
import AccesoDatos.Persistencia.Entidad.ELibro;
import LogicaNegocio.Biblioteca.Area;
import LogicaNegocio.Biblioteca.Autor;
import LogicaNegocio.Biblioteca.Libro;
import LogicaNegocio.Biblioteca.PalabraClave;
import MainBiblioSoft.BiblioSoft;
import java.util.Iterator;
import java.util.List;
import javax.persistence.EntityExistsException;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.PersistenceUnit;
import javax.persistence.Query;
import javax.persistence.RollbackException;

/**
 * Esta clase en java es el gestor de persistencia
 * de objetos Libro en la base de datos BiblioSoft.
 *
 * @author sebaxtian
 * Archivo: ManagerLibro.java
 * @version 1.0
 * Fecha: dom may  2 18:17:03 COT 2010
 */


public class ManagerLibro {

    @PersistenceUnit
    private EntityManagerFactory managerFactory;
    private EntityManager entityManager;

    /**
     * Metodo constructor, crea un gestor para la persistencia de Libro
     * 
     */
    public ManagerLibro() {
        managerFactory = BiblioSoft.managerFactory;
        entityManager = managerFactory.createEntityManager();
    }

    /**
     * Este metodo se encarga de la persistencia en la entidad Libro
     * de un objeto Libro.
     *
     * @param libro
     */
    public void crearLibro(Libro libro) throws RollbackException, EntityExistsException {
        entityManager.clear();
        ELibro entidadLibro = new ELibro();
        entidadLibro.setIsbn(libro.getIsbn());
        entidadLibro.setCodigoeditorial(libro.getCodigoEditorial());
        entidadLibro.setTitulo(libro.getTitulo());
        entidadLibro.setAnopublicacion(libro.getAnoPublicacion());
        entidadLibro.setIdioma(libro.getIdioma());
        entidadLibro.setActivo(libro.getActivo());
        entidadLibro.setCantbusquedas(libro.getCantidadBusquedas());
        //persiste el objeto en la entidad
        EntityTransaction transaccion = entityManager.getTransaction();
        try{
            transaccion.begin();
            entityManager.persist(entidadLibro);
        } catch (EntityExistsException ex) {
            throw ex;
        } finally {
            transaccion.commit();
        }
        entityManager.clear();
        //persistencia areas, autores y palabas del libro
        registrarAreas(libro);
        registrarAutores(libro);
        registrarPalabras(libro);
    }

    /**
     * Este metodo desactiva el uso de un libro en la biblioteca.
     * Y todos los ejemplares del mismo.
     *
     * @param isbn
     */
    public void desactivarLibro(Long isbn) {
        entityManager.clear();
        ELibro entidadLibro;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadLibro = entityManager.find(ELibro.class, isbn);
        transaccion.commit();
        if(entidadLibro != null){
            entidadLibro.setActivo(false);
            transaccion.begin();
            entityManager.merge(entidadLibro);
            transaccion.commit();
            Query consulta = entityManager.createQuery("UPDATE EEjemplar e SET e.disponible = :disponible WHERE e.isbn = :isbn");
            consulta.setParameter("disponible", false);
            consulta.setParameter("isbn", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            consulta = entityManager.createQuery("UPDATE ELibro e SET e.activo = :activo WHERE e.isbn = :isbn");
            consulta.setParameter("activo", false);
            consulta.setParameter("isbn", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
        }
        entityManager.clear();
    }

    /**
     * Este metodo permite actualizar un libro de la base de datos.
     * 
     * @param isbn
     * @param libro
     */
    public void actualizarLibro(Long isbn, Libro libro) {
        entityManager.clear();
        ELibro entidadLibro;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadLibro = entityManager.find(ELibro.class, isbn);
        transaccion.commit();
        if(entidadLibro != null){
            entidadLibro.setIsbn(libro.getIsbn());
            entidadLibro.setCodigoeditorial(libro.getCodigoEditorial());
            entidadLibro.setTitulo(libro.getTitulo());
            entidadLibro.setAnopublicacion(libro.getAnoPublicacion());
            entidadLibro.setIdioma(libro.getIdioma());
            entidadLibro.setActivo(libro.getActivo());
            if(!libro.getActivo()){
                desactivarLibro(isbn);
            }
            entidadLibro.setCantbusquedas(libro.getCantidadBusquedas());
            transaccion.begin();
            entityManager.merge(entidadLibro);
            transaccion.commit();
            Query consulta = entityManager.createQuery("UPDATE EEscrito e SET e.eEscritoPK.isbn = :isbnnuevo WHERE e.eEscritoPK.isbn = :isbnanterior");
            consulta.setParameter("isbnnuevo", libro.getIsbn());
            consulta.setParameter("isbnanterior", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            consulta = entityManager.createQuery("UPDATE EAsignado e SET e.eAsignadoPK.isbn = :isbnnuevo WHERE e.eAsignadoPK.isbn = :isbnanterior");
            consulta.setParameter("isbnnuevo", libro.getIsbn());
            consulta.setParameter("isbnanterior", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            consulta = entityManager.createQuery("UPDATE EDescribir e SET e.eDescribirPK.isbn = :isbnnuevo WHERE e.eDescribirPK.isbn = :isbnanterior");
            consulta.setParameter("isbnnuevo", libro.getIsbn());
            consulta.setParameter("isbnanterior", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
            consulta = entityManager.createQuery("UPDATE EEjemplar e SET e.isbn = :isbnnuevo WHERE e.isbn = :isbnanterior");
            consulta.setParameter("isbnnuevo", libro.getIsbn());
            consulta.setParameter("isbnanterior", isbn);
            transaccion.begin();
            consulta.executeUpdate();
            transaccion.commit();
        }
        entityManager.clear();
    }

    /**
     * Este metodo permite obtener un libro identificado con isbn
     * retorna null si el libro no existe.
     *
     * @param isbn
     * @return libro
     */
    public Libro obtenerLibro(Long isbn) {
        entityManager.clear();
        ELibro entidadLibro;
        Libro libro = null;
        EntityTransaction transaccion = entityManager.getTransaction();
        transaccion.begin();
        entidadLibro = entityManager.find(ELibro.class, isbn);
        transaccion.commit();
        if(entidadLibro != null){
            libro = new Libro();
            libro.setIsbn(entidadLibro.getIsbn());
            libro.setCodigoEditorial(entidadLibro.getCodigoeditorial());
            libro.setTitulo(entidadLibro.getTitulo());
            libro.setAnoPublicacion(entidadLibro.getAnopublicacion());
            libro.setIdioma(entidadLibro.getIdioma());
            libro.setActivo(entidadLibro.getActivo());
            libro.setCantidadBusquedas(entidadLibro.getCantbusquedas());
        }
        entityManager.clear();
        return libro;
    }

    private void registrarAutores(Libro libro) {
        entityManager.clear();
        List<Autor> listaAutores = libro.getListaAutores();
        Iterator iterador = listaAutores.iterator();
        EntityTransaction transaccion = entityManager.getTransaction();
        while(iterador.hasNext()) {
            Autor autor = (Autor)iterador.next();
            EEscrito entidadEscrito = new EEscrito(libro.getIsbn(), autor.getCodigoAutor());
            transaccion.begin();
            entityManager.persist(entidadEscrito);
            transaccion.commit();
        }
        entityManager.clear();
    }

    private void registrarAreas(Libro libro) {
        entityManager.clear();
        List<Area> listaAreas = libro.getListaAreas();
        Iterator iterador = listaAreas.iterator();
        EntityTransaction transaccion = entityManager.getTransaction();
        while(iterador.hasNext()) {
            Area area = (Area)iterador.next();
            EAsignado entidadAsignado = new EAsignado(libro.getIsbn(), area.getCodigoArea());
            transaccion.begin();
            entityManager.persist(entidadAsignado);
            transaccion.commit();
        }
        entityManager.clear();
    }

    private void registrarPalabras(Libro libro) {
        entityManager.clear();
        List<PalabraClave> listaPalabras = libro.getListaPalabrasClave();
        Iterator iterador = listaPalabras.iterator();
        EntityTransaction transaccion = entityManager.getTransaction();
        while(iterador.hasNext()) {
            PalabraClave palabra = (PalabraClave)iterador.next();
            EDescribir entidadDescribir = new EDescribir(palabra.getIdPalabra(), libro.getIsbn());
            transaccion.begin();
            entityManager.persist(entidadDescribir);
            transaccion.commit();
        }
        entityManager.clear();
    }
}
